package de.seminar.lego3D;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.regex.Matcher;

import android.app.Activity;
import android.content.Context;
import android.content.Intent;
import android.content.SharedPreferences;
import android.hardware.Camera;
import android.hardware.Camera.CameraInfo;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.util.Log;
import android.view.Gravity;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.Button;
import android.widget.EditText;
import android.widget.FrameLayout;
import android.widget.PopupWindow;
import android.widget.FrameLayout.LayoutParams;
import android.widget.Toast;
import de.seminar.lego3D.qrCode.IntentIntegrator;
import de.seminar.lego3D.qrCode.IntentResult;
import de.seminar.lego3D.views.ColorView;
import de.seminar.lego3D.views.DragableSpace;
import de.seminar.lego3D.views.LegoView;
import de.seminar.lego3D.views.QRCodeView;

public class Lego3DActivity extends Activity {

	/** dragable space with lego view and color view **/
	private DragableSpace space;

	/** the current lego brick **/
	private Legobrick currentBrick = new Legobrick();

	/** context of the activity **/
	private Context context = this;

	/** send button **/
	private Button sendButton;

	/** flag that indicates, if a brick was chosen **/
	private boolean brickChosen = false;

	/** flag that indicates if a color was chosen **/
	private boolean colorChosen = false;

	/** the lego view **/
	private LegoView legoView;

	/** the color view **/
	private ColorView colorView;

	/** to store the color history **/
	private SharedPreferences colorValues;

	/** the colors **/
	private HashMap<String, Integer> colors;

	/** the connector to the server **/
	private ClientConnector connector;
	
	/** the qr code view **/
	private QRCodeView qrView;
	
	/** popup window to show the edit text **/
	private PopupWindow popup;
	
	/** the edit text view in the popup window **/
	private EditText editText;
	
	/** counter for unsuccessful scans **/
	private int scanCounter = 0;

	/**
	 * Handler to handle the callback of the brick changes
	 */
	private final Handler mBrickChooseCallback = new Handler() {

		@Override
		public void handleMessage(final Message msg) {
			super.handleMessage(msg);

			Bundle b = msg.getData();

			currentBrick.setLayout(b.getIntArray(Constants.LEGO_LAYOUT));

			brickChosen = true;
			if (brickChosen && colorChosen) {
				sendButton.setEnabled(true);
			}
		}
	};

	/**
	 * Handler to handle the callback of the color changes
	 */
	private final Handler mColorChooseCallback = new Handler() {

		@Override
		public void handleMessage(final Message msg) {
			super.handleMessage(msg);

			Bundle b = msg.getData();

			int c = b.getInt(Constants.LEGO_COLOR);
			currentBrick.setColor(c);
			legoView.setCurrentColorView(c);

			space.snapToScreen(0);

			// Toast.makeText(context, "color is: " +
			// b.getInt(Constants.LEGO_COLOR), Toast.LENGTH_SHORT).show();

			colorChosen = true;
			if (brickChosen && colorChosen) {
				sendButton.setEnabled(true);
			}
		}
	};
	
	/** Handler to receive callback from receiver thread when connection is established **/
	private final Handler mCommunicationCallbackHandler = new Handler() {

		@Override
		public void handleMessage(final Message msg) {
			super.handleMessage(msg);
			final Bundle bundle = msg.getData();
			if (bundle != null) {
				if (bundle.getBoolean(Constants.SUCCESSFUL)) {
					Toast.makeText(context, "Connection established", Toast.LENGTH_SHORT).show();
					connector.killReceiver();
				}
			}
		}
	};

	/** Called when the activity is first created. */
	@Override
	public void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);

		setContentView(R.layout.main);

		// restore color values
		colorValues = getSharedPreferences(Constants.COLOR_HISTORY,
				Context.MODE_PRIVATE);

		// write the default colors, only if there is nothing
		if (colorValues.getAll().isEmpty()) {
			loadDefaultColors();
		}

		// get the colors
		colors = (HashMap<String, Integer>) colorValues.getAll();

		for (String s : colors.keySet()) {
			Log.v("colors", s + " - " + colors.get(s));
		}

		connector = new ClientConnector(this, mCommunicationCallbackHandler);

		space = (DragableSpace) findViewById(R.id.space);

		legoView = new LegoView(this, mBrickChooseCallback);
		sendButton = legoView.getSendButton();

		colorView = new ColorView(this, mColorChooseCallback, colors.values()
				.toArray());
		
		popup = new PopupWindow(space, ViewGroup.LayoutParams.FILL_PARENT,
				ViewGroup.LayoutParams.FILL_PARENT, true);
		View view =  LayoutInflater.from(context).inflate(R.layout.popup, null, false);
		editText = (EditText) view.findViewById(R.id.IP);
		popup.setContentView(view);

		qrView = new QRCodeView(context);
	//	camView = new CameraView(context, qrCodeCallback, getIntent(), new ViewfinderResultPointCallback(qrView));
		
//		FrameLayout v = (FrameLayout) LayoutInflater.from(context).inflate(R.layout.cam_and_qr, null, false);
//		
//		v.addView(qrView);
//		
//		space.addView(v); //screen 0
		space.addView(legoView); // screen 1
		space.addView(colorView); //screen 2
		
		//space.setToScreen(0);
	}

	@Override
	protected void onResume() {
		super.onResume();
	}

	@Override
	protected void onStop() {
		super.onStop();

		storeColors();
	}
	
//	@Override
//	public void onRestart() {
//		
//	}
	
	/**
	 * Causes to do a QR Code scan via Intent. (see at
	 * http://code.google.com/p/zxing/wiki/ScanningViaIntent)
	 */
	private void doQRCodeScan() {
		IntentIntegrator
				.initiateScan(
						this,
						"Install Barcode Scanner?",
						"This application requires Barcode Scanner. Would you like to install it?",
						"Yes", "No", "QR_CODE");
	}
	
	/**
	 * Handles the result of the QR Code scan, and causes the client connector to connect, if a valid IP address was decoded.
	 */
	public void onActivityResult(int requestCode, int resultCode, Intent intent) {
		IntentResult scanResult = IntentIntegrator.parseActivityResult(
				requestCode, resultCode, intent);
		if (scanResult != null) {
			String content = scanResult.getContents();
			connector.start(content);
		} else {
			Toast.makeText(this, "QR Code detection not successful",
					Toast.LENGTH_SHORT).show();
		}
	}
	
	
	@Override
	protected void onDestroy() {
		connector.sendDisconnect();
		connector.kill();
		
		super.onDestroy();
	}

	/**
	 * Causes the client connector to send a new brick message to the server and
	 * clears the screen.
	 * 
	 * @param sfNormal
	 *            - the view representing the button
	 */
	public void onClickSend(View sfNormal) {
//		Toast.makeText(this, "clicked", Toast.LENGTH_SHORT).show();
		//TODO: WHY CLEAR?
		//clearSelection();
		//sendButton.setEnabled(false);

		connector.sendBirckInformation(currentBrick);
	}
	
	/**
	 * Opens a camera view and starts a QR Code detection, for decoding the server IP.
	 * 
	 * @param sfNormal - the view representing the button
	 */
	public void onClickConnect(View sfNormal) {
		doQRCodeScan();
	}

	/**
	 * Clears the color view. Only the default color set remains.
	 * 
	 * @param sfNormal
	 *            - the view representing the button
	 */
	public void onClickClear(View sfNormal) {
		colorView.clearColors();
		storeColors();

		loadDefaultColors();
		colors = (HashMap<String, Integer>) colorValues.getAll();

		colorView.setColors(colors.values().toArray());
	}
	
	/**
	 * Applies the input on the edit text to the client connector
	 * 
	 * @param sfNormal - the view representing the button
	 */
	public void onClickApply(View sfNormal) {
		String s = editText.getText().toString();
		if (s.equalsIgnoreCase("")) {
			Toast.makeText(context, "No input. Please try again.", Toast.LENGTH_SHORT).show();
		} else {
			connector.start(s);
			popup.dismiss();
		}
	}
	
	/**
	 * Cancels the popup window.
	 * 
	 * @param sfNormal - the view representing the button
	 */
	public void onClickCancel(View sfNormal) {
//		camView.setKilledFlag(false);
//		camView.requestLayout();
		popup.dismiss();
	}

	/**
	 * Loads the default color set, and stores it.
	 */
	private void loadDefaultColors() {
		SharedPreferences.Editor colorValuesEditor = colorValues.edit();

		for (String s : Constants.defaultColors.keySet()) {
			colorValuesEditor.putInt(s, Constants.defaultColors.get(s));
		}

		colorValuesEditor.apply();
	}

	/**
	 * stores the colors in the preferences
	 */
	private void storeColors() {
		ArrayList<Integer> colsTemp = colorView.getColors();

		SharedPreferences.Editor colorValuesEditor = colorValues.edit();

		colorValuesEditor.clear();
		colorValuesEditor.apply();

		for (Integer i : colsTemp) {
			colorValuesEditor.putInt(i + "", i);
		}

		colorValuesEditor.apply();
	}

	/**
	 * clears the selection of the brick and color
	 */
	private void clearSelection() {
		brickChosen = false;
		colorChosen = false;
		legoView.clearSelection();
	}
}